home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CD World 1998 January
/
CD World - Ocak 1998.iso
/
misc
/
dbase55
/
disk7
/
extern.pak
/
DBEXTERN.PRG
< prev
next >
Wrap
Text File
|
1996-01-05
|
14KB
|
420 lines
*******************************************************************************
*
* PROGRAM: dbextern.prg
*
* WRITTEN BY: Borland Samples Group
*
* DATE: 1/94
*
* UPDATED: 5/94
*
* REVISION: $Revision: 2.10 $
*
* VERSION: Visual dBASE
*
* DESCRIPTION: Examples that shows how the EXTERN system can be used.
*
* PARAMETERS: Number of example to execute, 0 for all.
*
* CALLS: Windows functions and calls to dbextern.dll
*
* USAGE: DO dbextern with <example#>
* Where <example#> can be from 1 to 11, or 0 for all.
*
*******************************************************************************
*******************************************************************************
*
* Introduction:
* The EXTERN system is an extension of Visual dBASE that allows
* Visual dBASE programs to interface with DLL's written in Windows compatible
* languages. Exported functions from a DLL can be called from a Visual dBASE
* program and those DLL functions can call back into Visual dBASE using the
* mechanism of setting and executing codeblocks.
* DLL functions can be called with arguments of simple type, like numeric,
* float, and character, but with the inclusion of the "dbasevar.h" file
* more complex Visual dBASE variables can be passed to functions in a DLL and
* caught in "DBaseVar" variables. Through these DBaseVar variables the
* DLL can access and manipulate Visual dBASE variables.
*
* General format to declare an EXTERN function:
*
* EXTERN [<callconvention>] <returntype> <funcname> | <user defined funcname>
* ([parameters]) [<path>] <dllname> [FROM <expC> | <expN>]
* where:
* <callconvention> = CDECL or nothing for implied PASCAL.
* <returntype> = One of CVOID | CSTRING | CWORD | CLONG | CLOGICAL |
* CDOUBLE | CHANDLE | CINT | CVAR.
* <funcname> = Name of the function you want to call.
* <user defined funcname> = Name you give to the function. Required if
* using the FROM option.
* <parameters> = parameters of the types CSTRING | CWORD | CLONG |
* CDOUBLE | CPTR | CVAR | CHANDLE | ... | CINT | CVOID |
* CLOGICAL.
* <path> = Optional path to DLL, defaults to Windows DLL search path.
* <dllname> = Name of the DLL that contains the function.
* FROM <expC> | <expN> = name of the function in the DLL or the ordinal #
* of the function in the DLL if you rename the
* function above in <user defined funcname>.
*
* NOTE: the CVAR and ... options apply only to DLL's that are written
* for Visual dBASE using the dbasevar.h file.
*
* After the EXTERN statement you can use the function just like any
* other function in your Visual dBASE statements.
*
*
* Following are examples that show different ways to use the
* EXTERN system. Most examples have a C/C++ counterpart in the
* dbextern.cpp file so look there to see how things work in the DLL.
*
* Look in the dbasevar.h header file for more information about how
* Visual dBASE variables are declared and used on the DLL side.
*
*******************************************************************************
parameters whichone
set talk off
* Check parameters
tellusage = 1
* Any parameters at all?
IF pcount() > 0
* Parameter numeric?
IF type( "whichone" ) = "N"
* Parameter in range?
IF whichone <= 11 .AND. whichone >= 0
tellusage = 0
ENDIF
ENDIF
ENDIF
IF tellusage = 1
? "Usage: do dbextern with <example#>"
? "Where <example#> can be from 1 to 11, or 0 for all."
return
ENDIF
*******************************************************************************
*
* Example # 1.
*
* Some simple examples using the different types. Also demonstrates how
* to use the FROM option using the name of a PASCAL function.
*
*******************************************************************************
IF whichone = 1 .or. whichone = 0
EXTERN CLOGICAL TypeTest1( CSTRING,CWORD,CDOUBLE ) dbextern.dll
EXTERN CLOGICAL T1( CSTRING,CWORD,CDOUBLE ) dbextern.dll FROM "TypeTest1"
EXTERN CDECL CDOUBLE TypeTest2( CPTR, CLONG, CVAR ) dbextern.dll
? "TypeTest1( should be .T. ) =", TypeTest1( "string", 123, 321.123 )
? "T1( should be .T. ) =", T1( "string", 123, 321.123 )
d1 = 234.4
? "TypeTest2( should be 857.50 ) =", TypeTest2( "123.1", 500, d1 )
ENDIF
*******************************************************************************
*
* Example # 2.
*
* Execute Windows API functions:
*
*******************************************************************************
IF whichone = 2 .or. whichone = 0
EXTERN CWORD MessageBox( CWORD, CSTRING, CSTRING, CWORD ) user.exe
EXTERN CWORD GetFocus() user.exe
MessageBox( GetFocus(), "Hello", "Message", 0 )
ENDIF
*******************************************************************************
*
* Example # 3.
*
* The Visual dBASE objects you send as CVAR's can be of various types.
* In the DLL you can get the type of the object with Type().
*
*******************************************************************************
IF whichone = 3 .or. whichone = 0
EXTERN CSTRING WhichType( CVAR ) dbextern.dll
o = .T.
? ".T.:", WhichType( o )
o = 123.4
? "123.4:", WhichType( o )
o = 1234
? "1234:", WhichType( o )
o = "hello"
? "'hello':", WhichType( o )
o = new object()
? "new object():", WhichType( o )
o = {|a| a=a }
? "{|a| a=a}:", WhichType( o )
ENDIF
*******************************************************************************
*
* Example # 4.
*
* Visual dBASE variables are passed by reference and are caught on the
* DLL side with a DBaseVar *. This makes it possible to modify
* Visual dBASE objects in the DLL. This example also demonstrates how
* to use the CVAR type as the return type of functions. In the
* source code of the DLL there are some hints on how to set up
* the prototypes for the corresponding C/C++ functions.
*
*******************************************************************************
IF whichone = 4 .or. whichone = 0
* We'll do a CDECL and a PASCAL function.
EXTERN CDECL CVAR ModifyAndAdd1( CVAR, CVAR ) dbextern.dll
EXTERN CVAR ModifyAndAdd2( CVAR, CVAR ) dbextern.dll
d1 = 2.5
d2 = 3
result = .F.
result = ModifyAndAdd1( d1, d2 )
? "d1 before 2.5, after", d1
? "d2 before 3, after", d2
? "result before .F., after", result
d1 = 2.5
d2 = 3
result = .F.
result = ModifyAndAdd2( d1, d2 )
? "d1 before 2.5, after", d1
? "d2 before 3, after", d2
? "result before .F., after", result
ENDIF
*******************************************************************************
*
* Example # 5.
*
* Members of a class object passed to a DLL are also accessible.
* This leads to one way to execute Windows API functions that require
* structs as parameters. Here we call into a DLL that translates the
* Visual dBASE class object into a C struct and does the actual calling. The
* result of the call is piped back into a Visual dBASE object.
*
*******************************************************************************
IF whichone = 5 .or. whichone = 0
EXTERN CDECL CVOID WSetRect( CVAR,CWORD,CWORD,CWORD,CWORD ) dbextern.dll
EXTERN CVOID WIntersectRect( CVAR,CVAR,CVAR ) dbextern.dll
r1 = new Rect()
r2 = new Rect()
r3 = new Rect()
WSetRect( r1, 10,20,100,200 )
WSetRect( r2, 50,60,150,260 )
WIntersectRect( r3, r1, r2 )
? "Rect after intersect:"
? r3.left, r3.top, r3.right, r3.bottom
ENDIF
*******************************************************************************
*
* Example # 6.
*
* Through the use of code blocks Visual dBASE code can be executed on the fly
* from inside the DLL. This example passes 2 objects and through code
* blocks the objects are compared and changed in the DLL.
*
*******************************************************************************
IF whichone = 6 .or. whichone = 0
EXTERN CSTRING CheckAndChange( CVAR, CVAR ) dbextern.dll
a = 5; b = 5
? CheckAndChange( a, b )
? "a and b =", a, b
ENDIF
*******************************************************************************
*
* Example # 7.
*
* Visual dBASE arrays can be accessed in the DLL. This example computes the
* average of the members of an array created on the Visual dBASE side.
* The DLL function is called without any parameters. To be able to
* get at the array, the DLL function is executed through a function
* pointer that is a member of the same object as the array. Inside
* the DLL you can get the "this" pointer of the object the calling
* functionptr belongs to, and through that "this" pointer you can
* access the array members.
* Normally ofcourse you can just pass the array as a CVAR.
*
*******************************************************************************
IF whichone = 7 .or. whichone = 0
EXTERN CDECL CDOUBLE ComputeAverage() dbextern.dll
d = new array( 5 )
d.average = ComputeAverage
d[1] = 1.1
d[2] = 2.2
d[3] = 3.3
d[4] = 4.4
? "Computed average:", d.average()
ENDIF
*******************************************************************************
*
* Example # 8.
*
* This example puts into "practice" a majority of the available
* memberfunctions of the DBaseVar class. Not much to see on this side,
* but check out the corresponding function in the DLL.
*
*******************************************************************************
IF whichone = 8 .or. whichone = 0
EXTERN CLONG TestABunch( CVAR ) dbextern.dll
p = new object()
? "TestABunch Errors:", TestABunch( p )
? "row one of array p:", p[1,1], p[1,2], p[1,3]
? "row two of array p:", p[2,1], p[2,2], p[2,3]
ENDIF
*******************************************************************************
*
* Example # 9.
*
* If a DLL is written in a language that can talk to DOS, you can take
* advantage of that. This example gets the complete DOS environment in
* one big string. The FROM option using ordinals is also used. Ordinal
* 14 refers to GetEnvString as can be seen in the dbextern.def file.
*
*******************************************************************************
IF whichone = 9 .or. whichone = 0
EXTERN CDECL CVOID GetEnvString( CVAR ) dbextern.dll
EXTERN CDECL CVOID Getit( CVAR ) dbextern.dll FROM 14
q1 = new object()
GetEnvString( q1 )
q2 = new object()
Getit( q2 )
? "First 40 chars of environment:"
? substr( q1,1,20 ) + substr( q2,21,20 )
ENDIF
*******************************************************************************
*
* Example # 10.
*
* This example shows how variable number of parameters can be implemented
* for CDECL functions, and how the FROM option works with CDECL functions.
*
*******************************************************************************
IF whichone = 10 .or. whichone = 0
EXTERN CDECL CDOUBLE AddNumbers(...) dbextern.dll
EXTERN CDECL CDOUBLE AddThem(...) dbextern.dll FROM "_AddNumbers"
a = 1.1
b = 2.2
c = 3.3
? "AddNumber(...) should be 6.60:",AddNumbers( a, b, c )
a = 2.1
b = 3.2
c = 4.3
? "AddThem(...) should be 9.60:",AddThem( a, b, c )
ENDIF
*******************************************************************************
*
* Example # 11.
*
* This example shows how a Visual dBASE object can be combined with an "hidden"
* C++ sister object. Each Visual dBASE object has its own unique C++ object.
* This allows a Visual dBASE object to "remember and store" its own details
* specific to the DLL in the C++ object instead of having to save it
* in the Visual dBASE object. Examples are the storing of filehandles, and
* filepointers when the DLL is servicing files.
* Another possibility is a form of late binding where at the time of
* creation of the C++ part a choice can be made from several derived
* classes based on a common parent object.
*
*******************************************************************************
IF whichone = 11 .or. whichone = 0
EXTERN CWORD DLLObjectInit( CWORD ) dbextern.dll
EXTERN CSTRING Doit() dbextern.dll
EXTERN CVOID Release() dbextern.dll
* Create 2 objects that bind with the same C++ class.
foo1 = new dBASEObject()
foo2 = new dBASEObject()
foo1.init( 1 )
foo2.init( 1 )
* One more object that binds with a different C++ class.
bar = new dBASEObject()
bar.init( 2 )
* The first 2 object have different information stored but
* behave similarly.
? "foo1.doit():", foo1.doit()
? "foo2.doit():", foo2.doit()
* The last one has different info AND behaves differently.
? "bar.doit():", bar.doit()
foo1.release()
foo2.release()
bar.release()
ENDIF
*******************************************************************************
*
* Class definitions.
*
*******************************************************************************
class Rect
this.left=0
this.top=0
this.right=0
this.bottom=0
endclass
class dBASEObject
this.init = DLLObjectInit
this.doit = Doit
this.release = Release
endclass
********************* End of dbextern.prg ************************************